package com.databasedictionary.utils;

import org.apache.commons.lang.ObjectUtils;
import org.apache.velocity.VelocityContext;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.databasedictionary.utils.StringUtil.lineToHump;


/**
 * 代码生成类
 * Created by liull on 2017/11/4.
 */
public class MybatisGeneratorForOracleUtil {

    // generatorConfig模板路径
    private static String generatorConfig_vm = "/template/generatorConfig.vm";
    // Service模板路径
    private static String service_vm = "/template/Service.vm";
    // ServiceMock模板路径
    private static String serviceMock_vm = "/template/ServiceMock.vm";
    // ServiceImpl模板路径
    private static String serviceImpl_vm = "/template/ServiceImpl.vm";
    // Controller模板路径
    private static String controller_vm = "/template/CRUDController.vm";
    // apiController模板路径
    private static String apicontroller_vm = "/template/ListController.vm";
    //系统
    private static String WIN = "win";


    private static String generatorConfig_xml;
    private static String basePath;
    private static String module;
    private static String package_name;
    private static String mytablePrefix;
    private static String ctime = new SimpleDateFormat("yyyy/M/d").format(new Date());

    /**
     * 查询所有表
     *
     * @param jdbcDriver
     * @param jdbcUrl
     * @param jdbcUserName
     * @param jdbcPassword
     * @param modu
     * @param database
     * @param tablePrefix
     * @param packageNa
     * @param lastInsertIdTables
     * @return
     * @throws Exception
     */
    public static List<Map<String, Object>> selectTable(String jdbcDriver,
                                                        String jdbcUrl,
                                                        String jdbcUserName,
                                                        String jdbcPassword,
                                                        String modu,
                                                        String database,
                                                        String tablePrefix,
                                                        String packageNa,
                                                        Map<String, String> lastInsertIdTables) throws Exception {
        package_name = packageNa;
        mytablePrefix = tablePrefix.split("_")[0];
        module = modu;
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith(WIN)) {
            generatorConfig_vm = MybatisGeneratorForOracleUtil.class.getResource(generatorConfig_vm).getPath().replaceFirst("/", "");
            service_vm = MybatisGeneratorForOracleUtil.class.getResource(service_vm).getPath().replaceFirst("/", "");
            serviceMock_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceMock_vm).getPath().replaceFirst("/", "");
            serviceImpl_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceImpl_vm).getPath().replaceFirst("/", "");
        } else {
            generatorConfig_vm = MybatisGeneratorForOracleUtil.class.getResource(generatorConfig_vm).getPath();
            service_vm = MybatisGeneratorForOracleUtil.class.getResource(service_vm).getPath();
            serviceMock_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceMock_vm).getPath();
            serviceImpl_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceImpl_vm).getPath();
        }
        String targetProject = "";
        basePath = MybatisGeneratorForOracleUtil.class.getResource("/").getPath().replace("/target/classes/", "").replace(targetProject, "").replaceFirst("/", "");
        generatorConfig_xml = MybatisGeneratorForOracleUtil.class.getResource("/").getPath().replace("/target/classes/", "") + "/src/main/resources/generatorConfig.xml";
        String entityBasePath = basePath.substring(0,basePath.lastIndexOf("/"))+"/common";
        targetProject = basePath + targetProject;
        String targetProject2 = entityBasePath;
        String sql = "select t.table_name as TABLE_NAME,u.COMMENTS as TABLE_COMMENT from user_tables t LEFT JOIN user_tab_comments u ON t.Table_Name=u.Table_Name where t.TABLE_NAME like '" + tablePrefix + "%'";

        System.out.println("========== 开始生成generatorConfig.xml文件 ==========");
        List<Map<String, Object>> tables = new ArrayList();
        try {
            VelocityContext context = new VelocityContext();
            Map<String, Object> table;

            // 查询定制前缀项目的所有表
            JdbcUtil jdbcUtil = new JdbcUtil(jdbcDriver, jdbcUrl, jdbcUserName, jdbcPassword);
            List<Map> result = jdbcUtil.selectByParams(sql, null);
            for (Map map : result) {
                System.out.println(map.get("TABLE_NAME"));
                String tableName = String.valueOf(map.get("TABLE_NAME"));
                table = new HashMap<String, Object>(4);
                table.put("table_name", map.get("TABLE_NAME"));
                table.put("table_comment", map.get("TABLE_COMMENT"));
                table.put("model_name", lineToHump(ObjectUtils.toString(map.get("TABLE_NAME"))));
                List tableColumn = jdbcUtil.getTable(tableName);
                //为生成页面及控制类所产生
                table.put("tableColumn", tableColumn);
                tables.add(table);
            }
            jdbcUtil.release();

            String targetProject_sqlMap = basePath + module + "/" + module;
            context.put("tables", tables);
            context.put("generator_javaModelGenerator_targetPackage", mytablePrefix + ".entity");
            context.put("generator_sqlMapGenerator_targetPackage", package_name + ".dao.mapper");
            context.put("generator_javaClientGenerator_targetPackage", package_name + ".dao");
            context.put("targetProject", targetProject);
            context.put("targetProject2", targetProject2);
            context.put("targetProject_sqlMap", targetProject_sqlMap);
            context.put("generator_jdbc_password", jdbcPassword);
            context.put("last_insert_id_tables", lastInsertIdTables);
            VelocityUtil.generate(generatorConfig_vm, generatorConfig_xml, context);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("========== 结束生成generatorConfig.xml文件 ==========");
        return tables;
    }
    public static List<Map<String, Object>> selectTable2(String jdbcDriver,
                                                        String jdbcUrl,
                                                        String jdbcUserName,
                                                        String jdbcPassword,
                                                        String modu,
                                                        String database,
                                                        String tablePrefix,
                                                        String packageNa,
                                                        Map<String, String> lastInsertIdTables) throws Exception {
        package_name = packageNa;
        mytablePrefix = tablePrefix.split("_")[0];
        module = modu;
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith(WIN)) {
            String mypath = ResourceUtils.getURL("classpath:").getPath();
            generatorConfig_vm = mypath + generatorConfig_vm;
            service_vm = mypath + service_vm;
            serviceMock_vm = mypath + serviceMock_vm;
            serviceImpl_vm = mypath + serviceImpl_vm;
        } else {
            generatorConfig_vm = MybatisGeneratorForOracleUtil.class.getResource(generatorConfig_vm).getPath();
            service_vm = MybatisGeneratorForOracleUtil.class.getResource(service_vm).getPath();
            serviceMock_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceMock_vm).getPath();
            serviceImpl_vm = MybatisGeneratorForOracleUtil.class.getResource(serviceImpl_vm).getPath();
        }
        String targetProject = "";
        basePath = MybatisGeneratorForOracleUtil.class.getResource("/").getPath().replace("/target/classes/", "").replace(targetProject, "").replaceFirst("/", "");
        generatorConfig_xml = MybatisGeneratorForOracleUtil.class.getResource("/").getPath().replace("/target/classes/", "") + "/src/main/resources/generatorConfig.xml";
        String entityBasePath = basePath.substring(0,basePath.lastIndexOf("/"))+"/common";
        targetProject = basePath + targetProject;
        String targetProject2 = entityBasePath;
        String sql = "select t.table_name as TABLE_NAME,u.COMMENTS as TABLE_COMMENT from user_tables t LEFT JOIN user_tab_comments u ON t.Table_Name=u.Table_Name where t.TABLE_NAME like '" + tablePrefix + "%'";

        System.out.println("========== 开始生成generatorConfig.xml文件 ==========");
        List<Map<String, Object>> tables = new ArrayList();
        try {
            VelocityContext context = new VelocityContext();
            Map<String, Object> table;

            // 查询定制前缀项目的所有表
            JdbcUtil jdbcUtil = new JdbcUtil(jdbcDriver, jdbcUrl, jdbcUserName, jdbcPassword);
            List<Map> result = jdbcUtil.selectByParams(sql, null);
            for (Map map : result) {
                System.out.println(map.get("TABLE_NAME"));
                String tableName = String.valueOf(map.get("TABLE_NAME"));
                table = new HashMap<String, Object>(4);
                table.put("table_name", map.get("TABLE_NAME"));
                table.put("table_comment", map.get("TABLE_COMMENT"));
                table.put("model_name", lineToHump(ObjectUtils.toString(map.get("TABLE_NAME"))));
                List tableColumn = jdbcUtil.getTable(tableName);
                //为生成页面及控制类所产生
                table.put("tableColumn", tableColumn);
                tables.add(table);
            }
            jdbcUtil.release();

            String targetProject_sqlMap = basePath + module + "/" + module;
            context.put("tables", tables);
            context.put("generator_javaModelGenerator_targetPackage", mytablePrefix + ".entity");
            context.put("generator_sqlMapGenerator_targetPackage", package_name + ".dao.mapper");
            context.put("generator_javaClientGenerator_targetPackage", package_name + ".dao");
            context.put("targetProject", targetProject);
            context.put("targetProject2", targetProject2);
            context.put("targetProject_sqlMap", targetProject_sqlMap);
            context.put("generator_jdbc_password", jdbcPassword);
            context.put("last_insert_id_tables", lastInsertIdTables);
            VelocityUtil.generate(generatorConfig_vm, generatorConfig_xml, context);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("========== 结束生成generatorConfig.xml文件 ==========");
        return tables;
    }


    /**
     * 生成Admin
     *
     * @param tables
     * @throws Exception
     */
    public static void createAdmin(List<Map<String, Object>> tables) throws Exception {
        System.out.println("========== 开始生成Controller ==========");
        //dubboProvider文件所需数据
        List<Map<String, Object>> dubboList = new ArrayList();
        for (int i = 0; i < tables.size(); i++) {
            String tableComment = ObjectUtils.toString(tables.get(i).get("table_comment"));
            //表列结构
            List tableColumn = (List) tables.get(i).get("tableColumn");
            String model = lineToHump(ObjectUtils.toString(tables.get(i).get("table_name")));
            String[] projectName = module.split("-");
            String ptName = projectName[projectName.length - 1];
            //生成web-api-controller
            System.out.println(basePath);
            String apiControllerPath = basePath + module + "/" + module + "/src/main/resources/returnpackage/controller/crud";
            String apiController = apiControllerPath + "/" + model + "CRUDController.java";
            VelocityContext context = new VelocityContext();
            context.put("package_name", package_name);
            context.put("mytablePrefix", mytablePrefix);
            context.put("projectName", lineToHump(ptName));
            context.put("ptName", ptName);
            context.put("tableComment", tableComment);
            context.put("tableName", ObjectUtils.toString(tables.get(i).get("table_name")));
            context.put("tableName2", ObjectUtils.toString(tables.get(i).get("table_name")).replace("_",""));
            context.put("model", model);
            context.put("modelName", StringUtil.toLowerCaseFirstOne(model));
            context.put("ctime", ctime);
            context.put("tableColumn", tableColumn);
            fileCreate(controller_vm, apiController, context);
            Map dubbo = new HashMap(5);
            dubbo.put("package_name", package_name);
            dubbo.put("model", model);
            dubbo.put("mapping", StringUtil.toLowerCaseFirstOne(model));
            dubbo.put("tableComment", tableComment);
            dubboList.add(dubbo);
        }
    }

    /**
     * 生成Api层
     * @param tables
     * @throws Exception
     */
    public static void createApi(List<Map<String, Object>> tables) throws Exception {
        System.out.println("========== 开始生成API层  ==========");
        System.out.println("========== 开始生成API controller  ==========");
        //dubboProvider文件所需数据
        List<Map<String, Object>> dubboList = new ArrayList();
        for (int i = 0; i < tables.size(); i++) {
            String tableComment = ObjectUtils.toString(tables.get(i).get("table_comment"));
            //表列结构
            List tableColumn = (List) tables.get(i).get("tableColumn");
            String model = lineToHump(ObjectUtils.toString(tables.get(i).get("table_name")));
            String[] projectName = module.split("-");
            String ptName = projectName[projectName.length - 1];
            //生成web-api-controller
            System.out.println(basePath);
            String apiControllerPath = basePath + module + "/" + module + "/src/main/resources/returnpackage/controller/list";
            String apiController = apiControllerPath + "/" + model + "ListController.java";
            VelocityContext context = new VelocityContext();
            context.put("package_name", package_name);
            context.put("mytablePrefix", mytablePrefix);
            context.put("projectName", lineToHump(ptName));
            context.put("ptName", ptName);
            context.put("tableComment", tableComment);
            context.put("tableName", ObjectUtils.toString(tables.get(i).get("table_name")));
            context.put("tableName2", ObjectUtils.toString(tables.get(i).get("table_name")).replace("_",""));
            context.put("model", model);
            context.put("modelName", StringUtil.toLowerCaseFirstOne(model));
            context.put("ctime", ctime);
            context.put("tableColumn", tableColumn);
            fileCreate(apicontroller_vm, apiController, context);
            Map dubbo = new HashMap(5);
            dubbo.put("package_name", package_name);
            dubbo.put("model", model);
            dubbo.put("mapping", StringUtil.toLowerCaseFirstOne(model));
            dubbo.put("tableComment", tableComment);
            dubboList.add(dubbo);
        }
        System.out.println("========== 结束  生成controller ==========");
    }

    /**
     * 生成所有
     *
     * @param jdbc_driver
     * @param jdbc_url
     * @param jdbc_username
     * @param jdbc_password
     * @param modu
     * @param database
     * @param table_prefix
     * @param package_na
     * @param last_insert_id_tables
     * @throws Exception
     */
    public static void generator(String jdbc_driver,
                                 String jdbc_url,
                                 String jdbc_username,
                                 String jdbc_password,
                                 String modu,
                                 String database,
                                 String table_prefix,
                                 String package_na,
                                 Map<String, String> last_insert_id_tables) throws Exception {
        //查询所有表
        List<Map<String, Object>> tables = selectTable(jdbc_driver,jdbc_url,jdbc_username,jdbc_password,
                modu,
                database,
                table_prefix,
                package_na,
                last_insert_id_tables);
        //生成Api层
        createApi(tables);
        //生成Admin管理后台
        createAdmin(tables);

    }
    public static String generatorToZIP(String jdbc_driver,
                                 String jdbc_url,
                                 String jdbc_username,
                                 String jdbc_password,
                                 String modu,
                                 String database,
                                 String table_prefix,
                                 String package_na,
                                 Map<String, String> last_insert_id_tables) throws Exception {
        //查询所有表
        List<Map<String, Object>> tables = selectTable2(jdbc_driver,jdbc_url,jdbc_username,jdbc_password,
                modu,
                database,
                table_prefix,
                package_na,
                last_insert_id_tables);
        String apiControllerPath = basePath + module + "/" + module + "/src/main/resources/returnpackage/controller";
        String genmulu = basePath + module + "/" + module + "/src/main/resources/returnpackage";
        FileUtil.delFile(genmulu);
        //生成Api层
        createApi(tables);
        //生成Admin管理后台
        createAdmin(tables);
        return apiControllerPath;
    }




    private static void fileCreate(String model, String path, VelocityContext context) throws Exception {
        File serviceFile = new File(path);
        if (!serviceFile.exists()) {
            VelocityUtil.generate(model, path, context);
            System.out.println(path);
        }
    }

}
